package org.testis.testdriver;

import org.testis.testdriver.operations.TestPartOperationContext;
import org.testis.testdriver.AtofEnumaration.AtofLogLevel;
import org.testis.testdriver.AtofEnumaration.TestPartType;
import org.testis.testdriver.resultsmatrix.ThreeDResultsMatrix;
import org.testis.testdriver.exceptions.ImpossibleToAchieveSuccessPercentageException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Vector;

public class StepContainer extends TestPart {

    
    private boolean m_alwaysRun;
    private String[] m_dependentParts;
    private String m_dutModelName;
    private int m_invocationCount;
    private int m_threadPoolSize;
    private String m_versionATOF;
    private String m_versionDutFw;
    private String m_browserType;
    private int m_browserSpeed;
    private String m_currentIp;
    private String m_testBedIp;
    private String m_testPcMacAddr;
    private Integer m_languageId;
    private Integer m_profileId;
    private HashMap<String, String> m_serialConnData;
    private short m_Case_SuccessPercentage = 100;
    
    private boolean m_activateImpossibleSuccessPercFeature = false;
    private Integer mCurrentRunningTestPlan = 0;
    //Run Time Parameters.,
    private int m_howManyTimesWillContainerRun = 1;
    private Short m_TestCaseDataIndex = 0;
    private Integer m_invocationCountIndex = 0;
    private ThreeDResultsMatrix m_resultMatrix;
    private boolean m_retryWithOtherData = false;

    /**
     * Constructor that will be used for every StepContainer
     * @param testPartId Unique Id of the Test Part that is being created
     * @param testPartName Name of the Test Part that is being created
     * @param partDesc Description fo the Test Part that is being created
     * @param containerType Type of the Test Part (TestCase, TestCaseGroup, TestPlan etc...
     * 
     */
    public StepContainer(String testPartId,
            String testPartName,
            String partDesc,
            AtofEnumaration.TestPartType containerType) {
        this.m_containerType = containerType;
        this.m_testPartId = testPartId;
        this.m_testPartName = testPartName;
        this.m_partDescription = partDesc;
        this.m_testPartList = new LinkedList<TestPart>();

        switch (containerType) {
            case PostConditionCase:
            case PreConditionCase:
            case TestCase:
                m_runOperations =
                        new String[]{"TestPartOperationCalculateMaximumRunCount",
                            "TestPartOperationIterateChilds",
                            "TestPartOperationIncCaseDataIndex",
                            "TestPartOperationReturnPartResult"
                        };
                m_resultMatrix = new ThreeDResultsMatrix();
                break;
            case TestStepGroup:
                m_runOperations =
                        new String[]{"TestPartOperationCalculateMaximumRunCount",
                            "TestPartOperationIterateChilds",
                            "TestPartOperationIncCaseDataIndex",
                            "TestPartOperationReturnPartResult",
                            "TestPartOperationSetThreeDResult"
                        };
                m_resultMatrix = new ThreeDResultsMatrix();
                break;
            case TestCaseGroup:
                m_runOperations =
                        new String[]{"TestPartOperationIterateChilds",
                            "TestPartOperationReturnPartResult"
                        };
                break;
            case TestPlan:
                m_runOperations =
                        new String[]{"TestPartOperationSetTestPlanGlobals",
                            "TestPartOperationIterateChilds",
                            "TestPartOperationEndTestPlan",
                            "TestPartOperationReturnPartResult"
                        };
                break;
            case TestSuite:
                m_runOperations =
                        new String[]{"TestPartOperationResetPartResults",
                            "TestPartOperationIterateChilds",
                            "TestPartOperationReturnPartResult"
                        };
                break;
            default:
                m_runOperations =
                        new String[]{"TestPartOperationWhatTheHell"};
                break;
        }
    }

    /**
     * This method is used to set Test Case specific parameters. 
     *
     * @param  depParts  list of Test Parts that this Test Part object depends
     * @param  runAlways set this value to true if you want your Test Part 
     * to run even if the dpenedent Test Parts failed
     * @param  noOfRetryOnFail the number of retries if the TestPart fails.
     * @param  invokeCount the number of invocations of the TestPart object
     * @param  noOfThreads the number of the Thread Pools that will be used for 
     * Test Part invocations
     *      
     */
    public void setTestCaseParameters(int invokeCount,
            int noOfThreads,
            boolean activateImpSuccPercFeat) {
        if (invokeCount == 0) {
            invokeCount = 1;
        }

        this.m_invocationCount = invokeCount;
        this.m_threadPoolSize = noOfThreads;
        this.m_activateImpossibleSuccessPercFeature = activateImpSuccPercFeat;
    }

    /**
     * This method is used to set Test Part dependency parameters. 
     *
     * @param  depParts  list of Test Parts that this Test Part object depends
     * @param  runAlways set this value to true if you want your Test Part 
     * to run even if the dpenedent Test Parts failed     
     *      
     */
    public void setTestPartDependency(String[] depParts,
            boolean runAlways) {
        this.m_dependentParts = depParts;
        this.m_alwaysRun = runAlways;
    }

    /**
     * This method is sued to set the Test Plan Dut specific parameters.
     *
     * @param  versDutFw Version string of the DUT.      
     * @param  dutName Model name of the DUT.
     * @param  browserType Browser type that will be used.
     * @param  browserSpeed Browser spped that will be used.     
     * @param  currentIp currentIp of the Device under Test.     
     * @param  testBedIp testBedIp of the Device under Test.     
     */
    public void setTestPlanDutParameters(String versDutFw,
            String dutName,
            String browserType,
            int browserSpeed,
            String currentIp,
            String testBedIp) {
        this.m_versionDutFw = versDutFw;
        this.m_dutModelName = dutName;
        this.m_browserSpeed = browserSpeed;
        this.m_browserType = browserType;
        this.m_currentIp = currentIp;
        this.m_testBedIp = testBedIp;


    }

    /**
     * This method is sued to set the Test Plan Test Pc specific parameters.
     *
     * @param  versATOF  Version string of the current Test Framework.     
     * @param  testPcMacAddr Mac Address of target default test PC .
     */
    public void setTestPlanTestPcParameters(String versATOF,
            String testPcMacAddr) {
        this.m_versionATOF = versATOF;
        this.m_testPcMacAddr = testPcMacAddr;


    }

    /**
     * This method is used to set the Test Plan Global variables.
     *
     * @param  deviceLangId  id of the Language Variables File.     
     * @param  globalProfileId id of the Global Variables File.
     */
    public void setTestPlanGlobals(Integer deviceLangId,
            Integer globalProfileId) {
        this.m_languageId = deviceLangId;
        this.m_profileId = globalProfileId;
    }

    /**
     * This method is used to drive all the StepContainers and Test Steps and 
     * returns the result of the StepContainer execution.
     * Recursive execution is used because each StepContainer or TestStep is part
     * of the tree. Recursive execution starts from the first leaf of the tree
     * and each result of the iterated leafs is ANDed with the parents m_testPartResult
     * attribute. Also each result of the iterated Test Parts is ANDed with result
     * of their parent Test Part. 
     * If the current running TestPart is a StepContainer  and it is of 
     * StepContainerType.PreConditionCase type and its result is marked 
     * as false the execution and iteration of the parent Test Part which is usually
     * a TestCaseGroup is interrrupted and the system continues from the next nodes
     * after the parent node of the current TestPart. 
     * If the current runnning TestPart is a StepContainer of StepContainerType.PostConditionCase 
     * type and is a cirtical TestPart and its result is false a CriticalPostCaseException 
     * is thrown. 
     * If the current TestPart of StepContainerType.TestCase type  is marked as a 
     * RetryCaseWithOtherData the TestPart is itearated back to itself in order to retry
     * the TestCase with other available data in the DataObject that is attached
     * to the TestStep which is a child of the current TestCase.
     * If the current TestPart of TestStep type has multiple DataObjects attached to
     * it and is marked as DataArrayAppliesToCase; the parent of the TestStep which
     * is a TestCase is marked as RetryCaseWithOtherData in order to iterate the
     * parent TestCase back to itself.
     * If the current TestPart of TestStep type has multiple DataObjects attached to
     * it and is not marked as DataArrayAppliesToCase; the TestStep iterates back to 
     * itself to retry all other DataObjects with the TestStep.
     * If the current TestPart of TestStep type is marked as Critical and its result
     * is false; the iteration to the next Test Cases is interrupted.
     * 
     * @param  mode  The Debugging mode of the StepContainer execution.
     * @return boolean result of the TestPart execution
     *      
     */
    public boolean run(AtofEnumaration.DebuggingMode mode) throws
            InterruptedException {

        TestPartOperationContext currentContext = new TestPartOperationContext(
                this);
        if (this.getContainerType() == TestPartType.TestPlan) {
            ((StepContainer) this.getParent()).setCurrentRunningTestPlan(Integer.parseInt(this.getPartId()));

        }
        return currentContext.runContext(mode);


    }

    /**
     * This method is used to reset the Test Case Data Index and result sets
     * of the child Test Steps.      *      

     *      
     */
    public void resetCaseResults() {
        m_TestCaseDataIndex = (short) 0;
        // This index needs to be reseted at the end of each Invoations
        TestIterator curItemIter = this.createIter();
        curItemIter.init();
        while (curItemIter.isDone()) {
            curItemIter.next();
            curItemIter.currentItem().getCaseResultSet().clear();

        }


    }

    /**
     * This method is used to reset the Test Case Data Index and result sets
     * of the child Test Steps.
     *     
     *
     */
    public void resetCaseIndexes() {
        m_invocationCountIndex = 0;
        m_howManyTimesWillContainerRun = 1;

    }

    /**
     * This method is used to add TestPart object to the current TestPart object.
     * First we set the object itself as the parent of the TestPart that will be added
     * than we add the TestPart to the current object.
     * @param  testPart  The TestPart object that will be added.     
     *      
     */
    public void add(TestPart testPart) {
        testPart.setParent(this);
        this.m_testPartList.add(testPart);

    }

    /**
     * This method is used to remove TestPart object from the current TestPart object.
     * The testPart is removed from the current objects m_testPartList
     * @param  testPart  The TestPart object that will be removed.     
     *      
     */
    public void remove(TestPart testPart) {
        this.m_testPartList.remove(testPart);
    }

    public String getPartNameLongFromChild() {
        Integer testCaseDataIndex = this.getTestCaseDataIndex() + 1;
        Integer invokeIndex = this.getInvocationCountIndex() + 1;

        // Increase index value for PartName in logging but not for Guid
        // for logging structure.

        String testStepName = "[" + this.getContainerType().name() + "] "
                + m_testPartName + " ["
                + TestStringConstants.getInvokeCountString() + invokeIndex.toString()
                + TestStringConstants.getDataCountString()
                + testCaseDataIndex.toString() + "]";
        return testStepName;
    }

    public String getPartGuidLongFromChild() {
        Integer testCaseDataIndex = this.getTestCaseDataIndex() + 1;
        Integer invokeIndex = this.getInvocationCountIndex();
        String testStepGuid = m_partGuid + invokeIndex.toString()
                + testCaseDataIndex.toString();
        return testStepGuid;
    }

    public String getPartNameLongFromContainer() {
        Integer testCaseDataIndex = this.getTestCaseDataIndex() + 0;
        Integer invokeIndex = this.getInvocationCountIndex() + 1;

        // Increase index value for PartName in logging but not for Guid
        // for logging structure.

        String testStepName = "[" + this.getContainerType().name() + "] "
                + m_testPartName + " ["
                + TestStringConstants.getInvokeCountString() + invokeIndex.toString()
                + TestStringConstants.getDataCountString()
                + testCaseDataIndex.toString() + "]";
        return testStepName;
    }

    public String getPartGuidLongFromContainer() {
        Integer testCaseDataIndex = this.getTestCaseDataIndex() + 0;
        Integer invokeIndex = this.getInvocationCountIndex();
        String testStepGuid = m_partGuid + invokeIndex.toString()
                + testCaseDataIndex.toString();
        return testStepGuid;
    }

    /**
     * This method is used to create an Iterator over the current TestPart object.
     * Here the Iterator is the interface name and StepIterator is the concrete 
     * Iterator.      
     *      
     */
    public TestIterator createIter() {
        TestIterator iFace = new StepIterator(this);

        return iFace;
    }

    public int getBrowserSpeed() {
        return m_browserSpeed;
    }

    public String getBrowserType() {
        return m_browserType;
    }

    public short getCaseSuccessPercentage() {
        return m_Case_SuccessPercentage;
    }

    public void setCaseSuccessPercentage(short m_Case_SuccessPercentage) {
        this.m_Case_SuccessPercentage = m_Case_SuccessPercentage;
    }

    public Short getTestCaseDataIndex() {
        return m_TestCaseDataIndex;
    }

    public void setTestCaseDataIndex(Short dataArrayIndex) {
        this.m_TestCaseDataIndex = dataArrayIndex;
    }

    public boolean getAlwaysRun() {
        return m_alwaysRun;
    }

    public String getDutModelName() {
        return m_dutModelName;
    }

    public int getInvocationCount() {
        return m_invocationCount;
    }

    public int getThreadPoolSize() {
        return m_threadPoolSize;
    }

    public String getVersionATOF() {
        return m_versionATOF;
    }

    public String getVersionDutFw() {
        return m_versionDutFw;
    }

    public String[] getDependentParts() {
        return m_dependentParts;
    }

    public boolean getRetryCaseWithOtherData() {
        return this.m_retryWithOtherData;
    }

    public void setRetryCaseWithOtherData(boolean m_retryWithOtherData) {
        this.m_retryWithOtherData = m_retryWithOtherData;
    }

    public String getCurrentIp() {
        return m_currentIp;
    }

    public void setCurrentIp(String currentIp) {
        this.m_currentIp = currentIp;
    }

    public String getTestBedIp() {
        return m_testBedIp;
    }

    public void setTestBedIp(String m_testBedIp) {
        this.m_testBedIp = m_testBedIp;
    }

    public String getTestPcMacAddr() {
        return m_testPcMacAddr;
    }

    public Integer getLanguageId() {
        return m_languageId;
    }

    public Integer getProfileId() {
        return m_profileId;
    }

    public HashMap<String, String> getSerialConnData() {
        return m_serialConnData;
    }

    public void setSerialConnData(HashMap<String, String> m_serialConnData) {
        this.m_serialConnData = m_serialConnData;
    }

    public Integer getInvocationCountIndex() {
        return m_invocationCountIndex;
    }

    public void setInvocationCountIndex(Integer invCountIndex) {
        this.m_invocationCountIndex = invCountIndex;
    }

    public ThreeDResultsMatrix getResultMatrix() {
        return m_resultMatrix;
    }

    public void setResultMatrix(ThreeDResultsMatrix m_resultMatrix) {
        this.m_resultMatrix = m_resultMatrix;
    }

    public int getHowManyTimesWillContainerRun() {
        return m_howManyTimesWillContainerRun;
    }

    public void setHowManyTimesWillContainerRun(int howManyTimesWillContainerRun) {
        this.m_howManyTimesWillContainerRun = howManyTimesWillContainerRun;
    }

    public boolean getActivateImpossibleSuccessPercFeature() {
        return m_activateImpossibleSuccessPercFeature;
    }

    public void setActivateImpossibleSuccessPercFeature(
            boolean mActivateImpossibleSuccessPercFeature) {
        this.m_activateImpossibleSuccessPercFeature =
                mActivateImpossibleSuccessPercFeature;
    }

    /**
     * @return the mCurrentRunningTestPlan
     */
    public Integer getCurrentRunningTestPlan() {
        return mCurrentRunningTestPlan;
    }

    /**
     * @param mCurrentRunningTestPlan the mCurrentRunningTestPlan to set
     */
    public void setCurrentRunningTestPlan(Integer mCurrentRunningTestPlan) {
        this.mCurrentRunningTestPlan = mCurrentRunningTestPlan;
    }

    public boolean validateThreeDResultArray() {
        boolean isSuccessfull;
        int numberOfSucessResults = 0;
        int numberOfFailedResults = 0;
        int numberOfTotalRuns = 0;
        int numberOfTotalTries = 0; // Number of invoke * Number Of Data
        boolean curResult = this.getTestPartResult();
        short caseSuccessPerc = this.getCaseSuccessPercentage();
        Vector<Vector<Vector<Boolean>>> tsg3dArray = m_resultMatrix.get3dArray();
        int tsgInvokeCount = tsg3dArray.size();
        if (tsgInvokeCount == 0) {// The case where Container has
            //not invoked any therefore assume it is successfull
            isSuccessfull = curResult;
        } else {

            for (int x = 0; x < tsgInvokeCount; x++) {
                Vector<Vector<Boolean>> tsg2dArray = tsg3dArray.get(x);
                int testStepSize = tsg2dArray.size();
                if (testStepSize == 0) {// The case where TestStepGrup had
                    //no childs and childs results therefore
                    isSuccessfull = curResult;
                    break;
                } else {

                    Vector<Boolean> tsgResArray = tsg2dArray.get(0); // If we are here it is guranteed that index 0 exists
                    int dataCount = tsgResArray.size(); // here I find the number of datas of a step
                    numberOfTotalTries = tsgInvokeCount * dataCount;
                    if (dataCount == 0) {// The case where Test Step had
                        //no childs and childs results therefore
                        isSuccessfull = curResult;
                        break;

                    } else {
                        int dataIndex = 0;
                        while (dataIndex < dataCount) {
                            boolean caseSuccessful = true;
                            for (int y = 0; y < testStepSize; y++) {
                                Vector<Boolean> resArray = tsg2dArray.get(y);
                                Boolean result = resArray.get(dataIndex);
                                if (!result) {
                                    caseSuccessful = false;
                                    break;
                                }

                            }
                            if (caseSuccessful) {
                                numberOfSucessResults++;
                            } else {
                                numberOfFailedResults++;
                            }
                            numberOfTotalRuns++;

                            dataIndex++;
                        }
                    }

                }

            }
            int successPercentage = 100;
            if (numberOfTotalTries < m_howManyTimesWillContainerRun) {
                successPercentage = (numberOfSucessResults * 100)
                        / m_howManyTimesWillContainerRun;
            } else {
                successPercentage = (numberOfSucessResults * 100)
                        / numberOfTotalTries;
            }

            isSuccessfull =
                    successPercentage
                    >= caseSuccessPerc;


        }
        Byte res = 0;
        if (isSuccessfull) {
            res = 1;
        }
        String parentGuid = this.getParent().getPartGuid();
        String selfGuid = this.getPartGuid();
        String selfName = this.getPartName();
        String designTreeId = this.getPartId();
        int testPartType = this.getContainerType().ordinal();


        if (this.getContainerType() == TestPartType.TestStepGroup) {
            parentGuid = this.getParent().getPartGuidLongFromChild();
            selfGuid = this.getPartGuid() + this.getParent().
                    getPartGuidLongFromChild().replaceAll(this.getParent().
                    getPartGuid(),
                    "");
            //selfName = m_CurrentPart.getPartName();// Test Case Invocation
            // Count and Data Count information are useless in the partName
            // but necessary in the partGuid for uniqueness of logs. Because
            // Test Step Group will have more than one invcations and Datas.



        }
        NotificationSubjectSingleton.getInstance().notifyLogHeaderMessages(
                Integer.parseInt(designTreeId),
                testPartType,
                res,
                parentGuid,
                selfName,
                selfGuid,
                ExecutionGuidProvider.createInstance().
                getExistingExecId());

        if (numberOfTotalTries < m_howManyTimesWillContainerRun) {
            // This situation occurs when impossible success perc happens.

            NotificationSubjectSingleton.getInstance().notifyLogMessages(this.getPartName(),
                    AtofLogLevel.INFO,
                    TestStringConstants.getImpossibleSuccessPecrString()
                    + caseSuccessPerc + TestStringConstants.getSpaceBar()
                    + numberOfFailedResults
                    + TestStringConstants.getTestCasesOutOfString()
                    + numberOfTotalRuns + TestStringConstants.getTotalNumberOfExpectedRunString()
                    + m_howManyTimesWillContainerRun,
                    selfGuid);
        } else { // This situation occurs if all invocatioons and datas ran.
            NotificationSubjectSingleton.getInstance().notifyLogMessages(this.getPartName(),
                    AtofLogLevel.INFO,
                    TestStringConstants.getTestCaseResultValidationString()
                    + String.valueOf(caseSuccessPerc) + "... "
                    + numberOfSucessResults + TestStringConstants.getOfString()
                    + numberOfTotalTries
                    + TestStringConstants.getTestCaseValidationInfoString(),
                    selfGuid);
        }


        this.m_resultMatrix.get3dArray().clear();
        // We must reset the 3d results in order to not affect the other
        // runs about the same test suite and test case of that suite

        return isSuccessfull;

    }

    public void validateCurrentThreeDResultArray(boolean abortIfGuranteesToFail) {

        int numberOfFailedResults = 0;
        int numberOfTotalRuns = 0;

        short caseSuccessPerc = this.getCaseSuccessPercentage();
        Vector<Vector<Vector<Boolean>>> tsg3dArray = m_resultMatrix.get3dArray();
        int tsgInvokeCount = tsg3dArray.size();
        if (tsgInvokeCount != 0) {// If any invocations happened.

            for (int x = 0; x < tsgInvokeCount; x++) {
                Vector<Vector<Boolean>> tsg2dArray = tsg3dArray.get(x);
                int testStepSize = tsg2dArray.size();
                if (testStepSize == 0) {// The case where CaseContainer  had
                    //no childs and childs results therefore

                    break;
                } else {

                    Vector<Boolean> tsgResArray = tsg2dArray.get(0); // If we are here it is guranteed that index 0 exists
                    int dataCount = tsgResArray.size(); // here I find the number of datas of a step
                    //numberOfTotalTries = tsgInvokeCount * dataCount;
                    if (dataCount == 0) {// The case where Test Step had
                        //no childs and childs results therefore

                        break;

                    } else {
                        int dataIndex = 0;
                        while (dataIndex < dataCount) {
                            boolean caseSuccessful = true;
                            for (int y = 0; y < testStepSize; y++) {
                                Vector<Boolean> resArray = tsg2dArray.get(y);
                                Boolean result = resArray.get(dataIndex);
                                if (!result) {
                                    caseSuccessful = false;
                                    break;
                                }

                            }


                            boolean logOnlyLastCase = false;
                            // Because every time we will be reviewing
                            // all the invocations from the startup.

                            if (dataIndex == dataCount - 1 && x
                                    == tsgInvokeCount - 1) {
                                logOnlyLastCase = true;
                                // Logging only the final step is enough
                            }

                            Byte resByte = 1; //success

                            if (!caseSuccessful) {
                                numberOfFailedResults++;
                                resByte = 0;
                            }
                            numberOfTotalRuns++;

                            if (logOnlyLastCase) {


                                String curCaseGuid = this.getPartGuid() + String.valueOf(
                                        x)
                                        + String.valueOf(dataIndex + 1);

                                String curCaseName = this.getPartName()
                                        + " ["
                                        + TestStringConstants.getInvokeCountString() + String.valueOf(
                                        x + 1)
                                        + TestStringConstants.getDataCountString()
                                        + String.valueOf(dataIndex + 1) + "]";

                                // Do x+1 for only guid for only naming for guid leave x as it is.

                                String curCaseParentGuid =
                                        this.getPartGuid();

                                if (this.getContainerType()
                                        == TestPartType.TestStepGroup) {
                                    curCaseParentGuid = this.getPartGuid() + this.getParent().
                                            getPartGuidLongFromChild().replaceAll(this.getParent().
                                            getPartGuid(),
                                            "");
                                    curCaseGuid =
                                            this.getPartGuid() + String.valueOf(
                                            x) + String.valueOf(dataIndex + 1) + this.getParent().
                                            getPartGuidLongFromChild().replaceAll(this.getParent().
                                            getPartGuid(),
                                            "");
                                }



                                NotificationSubjectSingleton.getInstance().notifyLogHeaderMessages(
                                        Integer.parseInt(
                                        this.getPartId()),
                                        this.getContainerType().ordinal(),
                                        resByte,
                                        curCaseParentGuid,
                                        curCaseName,
                                        curCaseGuid,
                                        ExecutionGuidProvider.createInstance().
                                        getExistingExecId());

                                NotificationSubjectSingleton.getInstance().notifyLogMessages(curCaseName,
                                        AtofLogLevel.INFO,
                                        TestStringConstants.getValidatedTestCaseString(),
                                        curCaseGuid);

                            }

                            dataIndex++;
                        }
                    }

                }

            }

            int caseFailingPerc = 100 - caseSuccessPerc;

            int failedPercentage = (numberOfFailedResults * 100)
                    / m_howManyTimesWillContainerRun;

            boolean isImpossibleToPass =
                    failedPercentage
                    > caseFailingPerc;

            boolean lastRun = numberOfTotalRuns
                    == m_howManyTimesWillContainerRun;

            if (isImpossibleToPass && abortIfGuranteesToFail && !lastRun) {

                throw new ImpossibleToAchieveSuccessPercentageException(TestStringConstants.getImpossibleSuccessPecrString() + String.valueOf(
                        caseSuccessPerc));
            }




        }


        // If throwing exception do this.
        //
        // We must reset the 3d results in order to not affect the other
        // runs about the same test suite and test case of that suite



    }

    @Override
    public void resetTestPartRunTimeParameters() {
        TestIterator curItemIter = this.createIter();
        this.setTestPartResult(true);
        m_TestCaseDataIndex = 0;
        m_invocationCountIndex = 0;
        m_howManyTimesWillContainerRun = 1;
        m_retryWithOtherData = false;
        m_case_resultSet.clear();
        m_failedconditions.clear();
        if (m_resultMatrix != null) {
            m_resultMatrix.resetVectors();
        }



        curItemIter.init();
        while (curItemIter.isDone()) {
            curItemIter.next();
            curItemIter.currentItem().resetTestPartRunTimeParameters();

        }
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash =
                79 * hash + (this.m_retryWithOtherData ? 1 : 0);
        hash =
                79 * hash + (this.m_alwaysRun ? 1 : 0);
        hash =
                79 * hash
                + (this.m_dependentParts != null ? this.m_dependentParts.hashCode()
                : 0);
        hash =
                79 * hash
                + (this.m_dutModelName != null ? this.m_dutModelName.hashCode() : 0);
        hash =
                79 * hash + this.m_invocationCount;
        hash =
                79 * hash + this.m_threadPoolSize;
        hash =
                79 * hash
                + (this.m_versionATOF != null ? this.m_versionATOF.hashCode() : 0);
        hash =
                79 * hash
                + (this.m_versionDutFw != null ? this.m_versionDutFw.hashCode() : 0);
        hash =
                79 * hash
                + (this.m_browserType != null ? this.m_browserType.hashCode() : 0);

        hash =
                79 * hash + this.m_browserSpeed;
        hash =
                79 * hash
                + (this.m_currentIp != null ? this.m_currentIp.hashCode() : 0);
        hash =
                79 * hash
                + (this.m_testBedIp != null ? this.m_testBedIp.hashCode() : 0);
        hash =
                79 * hash
                + (this.m_testPcMacAddr != null ? this.m_testPcMacAddr.hashCode()
                : 0);
        hash =
                79 * hash
                + (this.m_TestCaseDataIndex != null
                ? this.m_TestCaseDataIndex.hashCode() : 0);
        hash =
                79 * hash
                + (this.m_languageId != null
                ? this.m_languageId : 0);
        hash =
                79 * hash
                + (this.m_invocationCountIndex != null
                ? this.m_invocationCountIndex : 0);

        hash =
                79 * hash
                + (this.m_profileId != null
                ? this.m_profileId : 0);

        hash =
                79 * hash + this.m_Case_SuccessPercentage;

        hash =
                79 * hash + (this.m_serialConnData != null ? this.m_serialConnData.hashCode() : 0);
        hash =
                79 * hash + super.hashCode();
        return hash;

    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof StepContainer) {
            return ((StepContainer) obj).hashCode() == this.hashCode();
        } else {
            return false;
        }
        /* return ((StepContainer)obj).hashCode() == this.hashCode() &&
        ((StepContainer)obj).superHasCode() == super.hashCode();*/
    }
}


